home *** CD-ROM | disk | FTP | other *** search
- /*======================================================================
- R P C . I N E T R A Y D . C
- doc: Mon Feb 24 16:24:35 1992
- dlm: Thu Aug 19 23:08:22 1993
- (c) 1992 ant@julia
- uE-Info: 430 24 T 0 0 72 10 2 8 ofnI
- ======================================================================*/
-
- /*#define VERBOSE /* babble */
- /*#define TRACEWORKERS /* trace worker pids */
-
- #include <string.h> /* The long and sad inclusion story */
- #include <signal.h>
- #include <netdb.h> /* Prefer system over rpc/netdb.h */
- #include <stdio.h>
- #include <pwd.h>
- #include <errno.h>
- #include <syslog.h>
- #include <sys/file.h> /* A/UX wants that */
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <sys/param.h>
- #include <sys/wait.h>
- #ifndef INADDR_ANY
- #include <netinet/in.h>
- #endif
- #include <rpc/rpc.h>
- #include "rayshade.h"
- #include "picture.h"
- #include "version.h"
- #include "patchlevel.h"
- #include "inetray.h"
- #include "config.h"
- #include "common.h"
- #include "irtrace.h"
- #include "utils.h"
- #include "lbuffer.h"
- #include "stderr.h"
-
- #define MAXARGS 256 /* max # of args allowed */
- #define ARGBUFSZE 8192 /* max buffer for args */
-
- extern int errno; /* for connection retry */
- extern void inetray_1(); /* generated dispatch routine */
-
- EXPORT int _rpcpmstart; /* Started by a port monitor ? */
-
- static int argc; /* argcount */
- static char *argv[MAXARGS]; /* argvector */
- static char argbuf[ARGBUFSZE]; /* buffer for argv */
- static int pid = -1; /* pid of child */
- static int bufPid = -1; /* pid of lBuffer */
- static char rName[MAXHOSTNAMELEN]; /* remote hostname */
- static int lSize; /* size of scanline */
- static int sock = -1; /* result socket */
- static XDR xdrs; /* result XDR stream */
- static int key; /* session key */
- static u_long progNum; /* program number (INETRAY + wid) */
- static uid_t uid; /* user id (ideal) */
- static int bufPipe[2]; /* pipe from live buffer */
- static char initialized = FALSE; /* files read */
- static int firstFrame; /* deferred startframe number */
- static char bufReadingSock = FALSE; /* live buffer is reading socket */
- static int rpcSock,proto; /* socket & proto to register */
- static SVCXPRT *transport; /* transport handle */
- static int bNr = -1; /* bNr of last request */
-
- /*----------------------------------------------------------------------*/
-
- static void parseQuote(s,spp,bpp) /* parse quoted arg */
- char s[]; int *spp,*bpp;
- {
- argv[argc] = &argbuf[*bpp];
- (*spp)++;
- while (s[*spp] != '\'') { /* copy simply */
- argbuf[(*bpp)++] = s[(*spp)++];
- }
- argbuf[(*bpp)++] = '\0';
- (*spp)++; /* skip quote char */
- }
-
- static void parseArgs(s) /* break up s into argv */
- char s[];
- {
- int bufp,sp,sl;
-
- argc = bufp = sp = 0;
- sl = strlen(s);
- while (sp < sl) {
- if (s[sp] != '\'') {
- sp++;
- continue;
- }
- parseQuote(s,&sp,&bufp);
- argc++;
- }
- argv[argc] = NULL;
- }
-
- static void exitClean(s) /* kill & exit */
- int s;
- {
- #ifdef VERBOSE
- SYSLOG(LOG_NOTICE,"exitClean(%d)",s);
- #endif
- if (pid > 0) kill(pid,SIGKILL);
- if (!_rpcpmstart)
- (void)pmap_unset(progNum,IRV1);
- CLOSELOG();
- closeStderr();
- exit(s);
- }
-
- /*----------------------------------------------------------------------*/
-
- static void checkAbort() /* abort on crash */
- {
- fd_set selRead;
- int status;
-
- signal(SIGALRM,checkAbort); /* sysV yummy dummy */
-
- #ifdef VERBOSE
- SYSLOG(LOG_NOTICE,"Checking for abort");
- #endif
- if (pid > 0) { /* check child exit stat */
- #ifdef VERBOSE
- SYSLOG(LOG_NOTICE,"Checking for child termination");
- #endif
- if (waitpid(pid,&status,WNOHANG) > 0) {
- pid = 0;
- if (status != 0) {
- SYSLOG(LOG_ERR,"Abort: worker exit status %d",status);
- exitClean(1);
- }
- }
- }
-
- if (sock == -1) { /* not yet set up */
- SYSLOG(LOG_ERR,"Lost INIT request");
- exitClean(1);
- }
-
- #ifdef VERBOSE
- SYSLOG(LOG_NOTICE,"Checking socket");
- #endif
-
- if (bufReadingSock) { /* watch out! */
- FD_ZERO(&selRead);
- FD_SET(bufPipe[IN],&selRead); /* check buffer pipe */
- if (select(bufPipe[IN]+1,&selRead,NULL,NULL,&now) < 0) {
- SYSLOG(LOG_ERR,"select(): %m");
- exitClean(1);
- }
- bufReadingSock = !FD_ISSET(bufPipe[IN],&selRead);
- }
-
- if (bufReadingSock) return; /* really reading -> wait */
-
- FD_ZERO(&selRead); /* check connection */
- FD_SET(sock,&selRead);
- if (select(sock+1,&selRead,NULL,NULL,&now) < 0) {
- SYSLOG(LOG_ERR,"select(): %m");
- exitClean(1);
- }
- if (FD_ISSET(sock,&selRead)) { /* read() would return 0 */
- SYSLOG(LOG_ERR,"Dispatcher disappeared");
- exitClean(1);
- }
- }
-
- static void setupTimer()
- {
- struct itimerval chkClntT;
-
- #ifdef VERBOSE
- SYSLOG(LOG_NOTICE,"setupTimer()");
- #endif
- chkClntT.it_interval.tv_sec = chkClntT.it_value.tv_sec = CHKCLNT;
- chkClntT.it_interval.tv_usec = chkClntT.it_value.tv_usec = 0;
- signal(SIGALRM,checkAbort);
- if (setitimer(ITIMER_REAL,&chkClntT,NULL) < 0) {
- SYSLOG(LOG_ERR,"setitimer: %m");
- exitClean(1);
- }
- }
-
- static void registerSelf() /* register self */
- {
- transport = svcudp_create(rpcSock);
- if (transport == NULL) {
- SYSLOG(LOG_ERR,"cannot create udp service.");
- exitClean(1);
- }
- if (!svc_register(transport,progNum,IRV1,inetray_1,proto)) {
- SYSLOG(LOG_ERR,"unable to register (%d,VER,udp)",progNum);
- exitClean(1);
- }
- #ifdef VERBOSE
- SYSLOG(LOG_NOTICE,"Opening Stderr");
- #endif
- if (openStderr("rpc.inetrayd") < 0) exitClean(1);
- }
-
- static void slaveSvcs(n) /* start secondary servers */
- int n; /* clean up & register */
- {
- int pid,thisProg;
-
- thisProg = progNum;
- while (n-- > 0) { /* start n */
- thisProg++;
- pid = fork();
- if (pid < 0) {
- SYSLOG(LOG_ERR,"fork: %m");
- exitClean(1);
- }
- if (pid == 0) { /* new server */
- progNum = thisProg;
- svc_destroy(transport);
- (void)pmap_unset(progNum,IRV1);
- _rpcpmstart = FALSE;
- rpcSock = RPC_ANYSOCK;
- proto = IPPROTO_UDP;
- registerSelf();
- setupTimer();
- #ifdef VERBOSE
- SYSLOG(LOG_NOTICE,"INIT: forked prog # %d",progNum);
- #endif
- return;
- }
- }
- }
-
- /*----------------------------------------------------------------------*/
-
- static void killSelf() /* received SIGINT(kill) signal */
- {
- if (!xdrrec_endofrecord(&xdrs,TRUE)) {
- SYSLOG(LOG_ERR,"xdrrec_endofrecord() failed");
- exitClean(1);
- }
- exit(0);
- }
-
- /*----------------------------------------------------------------------*/
-
- static writeit(dummy,buf,nbyte) /* XDR write routine */
- char *dummy,*buf; int nbyte;
- {
- int writ;
-
- writ = write(sock,buf,nbyte);
- if (writ < 0) SYSLOG(LOG_ERR,"XDR write: %m");
- return writ;
- }
-
- static void sendResult(bNr,bSz,block,skip) /* send whole resultblock back */
- int bNr,bSz; Scanline *block; int skip;
- {
- pixArr res;
- int i;
-
- bNr += skip;
- if (!xdr_int(&xdrs,&bNr)) {
- SYSLOG(LOG_ERR,"xdr_int() failed");
- exitClean(1);
- }
-
- res.pixArr_len = lSize;
- for (i=skip*bSz+1; i<=(skip+1)*bSz; i++) {
- res.pixArr_val = (xdrPix *)block[i].pix;
- if (!xdr_pixArr(&xdrs,&res)) {
- SYSLOG(LOG_ERR,"xdr_pixArr() failed");
- exitClean(1);
- }
- }
- if (!xdrrec_endofrecord(&xdrs,TRUE)) {
- SYSLOG(LOG_ERR,"xdrrec_endofrecord() failed");
- exitClean(1);
- }
- }
-
- /*----------------------------------------------------------------------*/
-
- void *init_1(param) /* init self */
- iPrm *param;
- {
- int wid,wpid;
- char wd[MAXPATHLEN],v[8],*cp,*getcwd();
- struct passwd *p;
- struct hostent *host;
- struct sockaddr_in name;
-
- #ifdef VERBOSE
- SYSLOG(LOG_NOTICE,"INIT:");
- #endif
- if (pid != -1) /* only once */
- return (void *)NULL;
-
- pid = 0; /* initialized */
- slaveSvcs(param->nSvcs-1); /* start 2nd svcs */
-
- signal(SIGINT,SIG_IGN); /* ignore kill signal */
-
- strncpy(rName,param->rName,MAXHOSTNAMELEN);
- key = param->key; /* session key */
-
- if (uid == 0) { /* set default uid */
- if (setuid(param->uid) < 0) {
- SYSLOG(LOG_NOTICE,"setuid: %m");
- }
- uid = geteuid(); /* get effective uid */
- if (uid == 0) {
- SYSLOG(LOG_ERR,"can't run as root");
- exitClean(1);
- }
- }
- p = getpwuid(uid); /* get user info */
- if (p == NULL) {
- SYSLOG(LOG_ERR,"illegal user id %d",uid);
- exitClean(1);
- }
-
- addHome(uid,param->cwd,wd); /* get right dir */
- if (chdir(wd) < 0) { /* try to get there */
- SYSLOG(LOG_NOTICE,"WARNING: chdir(%s): %m",wd);
- }
-
- if (key != 0) { /* only pinged */
- parseArgs(param->cmdLine);
- }
- /* init socket */
- if ((host = gethostbyname(rName)) == NULL) {
- SYSLOG(LOG_ERR,"gethostbyname(%s) failed!",rName);
- exitClean(1);
- }
- name.sin_family = AF_INET;
- name.sin_port = htons(param->rPort);
- memcpy((char *)&name.sin_addr,host->h_addr_list[0],host->h_length);
-
- if ((sock = socket(PF_INET,SOCK_STREAM,0)) < 0) {
- SYSLOG(LOG_ERR,"socket: %m");
- exitClean(1);
- }
- if (connect(sock,&name,sizeof(name)) < 0) {
- if (errno == ECONNREFUSED) { /* retry once */
- close(sock);
- sleep((rand()%2)+1); /* wait random time */
- if ((sock = socket(PF_INET,SOCK_STREAM,0)) < 0) {
- SYSLOG(LOG_ERR,"socket: %m");
- exitClean(1);
- }
- if (connect(sock,&name,sizeof(name)) < 0) {
- SYSLOG(LOG_ERR,"connect: %m");
- exitClean(1);
- }
- } else {
- SYSLOG(LOG_ERR,"connect: %m");
- exitClean(1);
- }
- }
-
- xdrrec_create(&xdrs,0,0,NULL,NULL,writeit); /* create XDR */
- xdrs.x_op = XDR_ENCODE;
- wid = progNum - INETRAY; /* send back info */
- if (!xdr_int(&xdrs,&wid)) { /* worker id */
- SYSLOG(LOG_ERR,"xdr_int() failed");
- exitClean(1);
- }
- wpid = getpid();
- if (!xdr_int(&xdrs,&wpid)) { /* pid */
- SYSLOG(LOG_ERR,"xdr_int() failed");
- exitClean(1);
- }
- cp = p->pw_name; /* user name */
- if (!xdr_string(&xdrs,&cp,32)) {
- SYSLOG(LOG_ERR,"xdr_string() failed");
- exitClean(1);
- }
- getcwd(wd,MAXPATHLEN); /* working dir */
- stripHead(STRIPHEAD,wd);
- stripHome(uid,wd);
- cp = wd;
- if (!xdr_string(&xdrs,&cp,MAXPATHLEN)) {
- SYSLOG(LOG_ERR,"xdr_string() failed");
- exitClean(1);
- }
- sprintf(v,"%s%d",VERSION,PATCHLEVEL); /* version check */
- cp = v;
- if (!xdr_string(&xdrs,&cp,8)) {
- SYSLOG(LOG_ERR,"xdr_string() failed");
- exitClean(1);
- }
-
- if (!xdrrec_endofrecord(&xdrs,TRUE)) {
- SYSLOG(LOG_ERR,"xdrrec_endofrecord() failed");
- exitClean(1);
- }
-
- if (param->sendIn) { /* receive file */
- if (pipe(bufPipe) < 0) {
- SYSLOG(LOG_ERR,"pipe: %m");
- exitClean(1);
- }
- bufReadingSock = TRUE; /* buffer is reading */
- bufPid = lPostBuffer(sock,bufPipe);
- }
-
- #ifdef VERBOSE
- SYSLOG(LOG_NOTICE,"INIT done");
- #endif
- return (void *)NULL; /* dont reply rpc */
- }
-
- int *wait_1(keyP) /* wait 4 worker 2 die */
- int *keyP;
- {
- int status,dPid;
- static int res = 0;
-
- #ifdef VERBOSE
- SYSLOG(LOG_NOTICE,"WAITING FOR: %d",pid);
- #endif
- if (pid < 0) exit(0); /* not initialized */
- if (*keyP != key) { /* authorize */
- return (int *)NULL;
- }
- if (pid > 0) { /* one has been started */
- reStartWait:
- if ((dPid = waitpid(pid,&status,0)) < 0) { /* wait for it */
- if (errno == EINTR) goto reStartWait;
- SYSLOG(LOG_ERR,"wait: %m");
- exitClean(1);
- }
- if (status != 0) {
- SYSLOG(LOG_NOTICE,"worker exit status %d",status);
- }
- if (dPid != pid) { /* what happened ? */
- kill(pid,SIGKILL); /* abort ! */
- SYSLOG(LOG_ERR,"pid of dead %d instead of %d",dPid,pid);
- exitClean(1);
- }
- #ifdef VERBOSE
- SYSLOG(LOG_NOTICE,"pid %d returned %d",dPid,status);
- #endif
- pid = 0;
- }
- #ifdef VERBOSE
- SYSLOG(LOG_NOTICE,"WAITING done");
- #endif
- return &res;
- }
-
- int *startframe_1(param) /* start new frame */
- sfPrm *param;
- {
- static int res = 0;
- int status;
-
- #ifdef VERBOSE
- SYSLOG(LOG_NOTICE,"STARTFRAME:");
- #endif
- if (pid < 0) exit(0); /* not initialized */
- if (param->key != key) { /* authorize */
- return (int *)NULL;
- }
- wait_1(&(param->key));
- if (initialized) /* start new frame */
- RSStartFrame(param->fNr);
- else /* defer */
- firstFrame = param->fNr;
- bNr = -1; /* clear saved block# */
- #ifdef VERBOSE
- SYSLOG(LOG_NOTICE,"STARTFRAME done");
- #endif
- return &res;
- }
-
- void *traceblock_1(param) /* trace block of lines */
- tbPrm *param;
- {
- int pgrp,status,saveIn,i;
- Scanline *resBlock,*Raytrace();
-
- #ifdef VERBOSE
- SYSLOG(LOG_NOTICE,"TRACEBLOCK msg received");
- #endif
- if (pid < 0) exit(0); /* not initialized */
- if (param->key != key) /* authorize */
- return (void *)NULL;
- if (bNr == param->bNr) /* message resent */
- return (void *)NULL;
- #ifdef VERBOSE
- SYSLOG(LOG_NOTICE,"TRACEBLOCK started");
- #endif
-
- bNr = param->bNr; /* avoid doublework */
-
- if (!initialized) { /* deferred stuff */
- #ifdef VERBOSE
- SYSLOG(LOG_NOTICE,"initializing");
- #endif
- if (bufPid > 0) { /* buffered stdin */
- saveIn = dup(IN);
- close(IN);
- dup(bufPipe[IN]);
- close(bufPipe[IN]);
- }
- lSize = RaytraceInit(argc,argv);
- if (bufPid > 0) { /* restore stdin */
- waitpid(bufPid,NULL,0);
- bufPid = -1;
- bufReadingSock = FALSE;
- close(IN);
- dup(saveIn);
- }
- RSStartFrame(firstFrame);
- initialized = TRUE;
- /* wait(NULL); /* get status */
- }
- wait_1(&(param->key));
- pid = fork(); /* make new */
- if (pid < 0) {
- SYSLOG(LOG_ERR,"fork: %m");
- exitClean(1);
- }
- if (pid == 0) { /* child */
- nice(NICEDAEMON); /* run nicely */
-
- signal(SIGINT,killSelf);
- resBlock = Raytrace(param->nBlocks*param->bSz,
- param->lNr);
- signal(SIGINT,SIG_IGN);
- for (i=0; i<param->nBlocks; i++)
- sendResult(param->bNr,
- param->bSz,
- resBlock,i);
- #ifdef VERBOSE
- SYSLOG(LOG_NOTICE,"> EXIT");
- #endif
- exit(0);
- }
- #ifdef TRACEWORKERS
- SYSLOG(LOG_NOTICE,"pid %d forked",pid);
- #endif
- #ifdef VERBOSE
- SYSLOG(LOG_NOTICE,"pid %d forked",pid);
- #endif
- return NULL; /* don't block */
- }
-
- int *kill_1(keyP) /* kill worker */
- int *keyP;
- {
- static int res = 0;
-
- #ifdef VERBOSE
- SYSLOG(LOG_NOTICE,"KILLING: %d",pid);
- #endif
- if (pid < 0) exit(0); /* not initialized */
- if (*keyP != key) { /* authorize */
- return (int *)NULL;
- }
- if (pid > 0) (void)kill(pid,SIGINT);
- return &res;
- }
-
- void *terminate_1(keyP) /* terminate */
- int *keyP;
- {
- #ifdef VERBOSE
- SYSLOG(LOG_NOTICE,"TERMINATE:");
- #endif
- if (pid < 0) exit(0); /* not initialized */
- if (*keyP != key) { /* authorize */
- return;
- }
- if (pid > 0) { /* force */
- kill(pid,SIGKILL);
- wait_1(keyP);
- }
- if (bufPid > 0)
- kill(bufPid,SIGKILL);
- #ifdef VERBOSE
- SYSLOG(LOG_NOTICE,"TERMINATE done");
- #endif
- /* if (progNum == INETRAY) /* wid == 0 */
- /* CLOSELOG();*/
- exitClean(0);
- }
-
- /*======================================================================*/
-
- int _rpcfdtype = SOCK_DGRAM; /* Whether Stream or Datagram ? */
-
- main(ac,av)
- int ac; char *av[];
- {
- struct sockaddr_in saddr;
- int asize = sizeof(saddr);
- int ssize = sizeof(int);
- int fd;
-
- _rpcpmstart = (ac == 1); /* logging */
- if (!_rpcpmstart) CLOSELOG();
- OPENLOG("rpc.inetrayd");
- #ifdef VERBOSE
- SYSLOG(LOG_NOTICE,"started!");
- #endif
- setupTimer();
-
- #ifdef VERBOSE
- SYSLOG(LOG_NOTICE,"Timer set up");
- #endif
- if (_rpcpmstart) { /* inetd */
- rpcSock = 0;
- proto = 0;
- if (getsockname(rpcSock, (struct sockaddr *)&saddr, &asize) < 0) {
- SYSLOG(LOG_ERR,"socket: %m");
- exitClean(1);
- }
- if (saddr.sin_family != AF_INET) {
- SYSLOG(LOG_ERR,"illegal protocol");
- exitClean(1);
- }
- if (getsockopt(0, SOL_SOCKET, SO_TYPE,
- (char *)&_rpcfdtype, &ssize) == -1) {
- SYSLOG(LOG_ERR,"getsockopt: %m");
- exitClean(1);
- }
- } else { /* inetray.starter */
- (void)pmap_unset(INETRAY,IRV1);
- rpcSock = RPC_ANYSOCK;
- proto = IPPROTO_UDP;
- }
-
- #ifdef VERBOSE
- SYSLOG(LOG_NOTICE,"trying to register self...");
- #endif
- uid = geteuid(); /* set up */
- progNum = INETRAY;
- registerSelf();
-
- #ifdef VERBOSE
- SYSLOG(LOG_NOTICE,"waiting for request...");
- #endif
- svc_run();
- SYSLOG(LOG_ERR,"svc_run returned");
- exitClean(1);
- /* NOTREACHED */
- }
-
-